package com.spt.ws.dao.impl;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.spt.fjj.service.models.common.AnnotationCommonService;
import com.spt.ws.dao.ITaskService;
import com.spt.ws.task.QuartzTaskFactory;

@Service
public class TaskServiceImpl extends AnnotationCommonService implements ITaskService {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Override
    public List<Map<String, Object>> getAllTask() {
        List<Map<String, Object>> li = Lists.newArrayList();
        String sql = "select to_char(id) id,TASKID,GROUPID,CRON,JOBNAME,BEAN,LASTSTATUS from t_task_info order by groupid,taskid";
        /*
         * Map<String, Object> map = Maps.newHashMap(); map.put("TASKID",
         * "TASKID_1"); map.put("GROUPID", "GROUPID_1"); map.put("CRON",
         * "0/2 * * * * ?"); map.put("JOBNAME", "firstJob"); map.put("BEAN",
         * "testtask1"); li.add(map); map = Maps.newHashMap(); map.put("TASKID",
         * "TASKID_2"); map.put("GROUPID", "GROUPID_2"); map.put("CRON",
         * "0/4 * * * * ?"); map.put("JOBNAME", "2NDJob"); map.put("BEAN",
         * "testtask2"); li.add(map);
         */
        return this._queryMultex(sql);
    }

    @Override
    public void addTask(Map<String, String> params) {
        String sql = "insert into t_task_info (id,TASKID,GROUPID,CRON,JOBNAME,BEAN,LASTSTATUS) values(SEQ_TASK_INFO.Nextval,?,?,?,?,?,'n')";
        this._update(sql, params.get("TASKID"), params.get("GROUPID"), params.get("CRON"), params.get("JOBNAME"),
                params.get("BEAN"));
    }

    @Override
    public int modifyTask(Map<String, String> params) {
        String id = params.get("ID");
        if (id == null)
            return -1;
        params.remove("ID");
        StringBuffer sqlb = new StringBuffer("update t_task_info set ");

        if (params.keySet().size() == 0)
            return 0;
        List<String> values = Lists.newArrayList();
        for (String key : params.keySet()) {
            if (key.startsWith("R_"))
                continue;
            sqlb.append(key).append("=?, ");
            values.add(params.get(key));
        }
        sqlb.deleteCharAt(sqlb.lastIndexOf(","));
        sqlb.append("  where id =? ");
        values.add(id);
        return this._update(sqlb.toString(), values.toArray());
    }

    @Override
    public int removeTask(String id) {
        return this._delete("delete from t_task_info where id = ?", id);
    }

    @Override
    public int setLastStatus(String id, String status) {
        String sql = "update t_task_info set  LASTSTATUS = ? where id =?";

        return this._update(sql, status, id);
    }

    @Override
    public void autoUpdate(Map<String, List<String>> scanedTasks) {
        // String cleanSql = "delete from TASK_INFO where taskid in (inparams)";
        if (scanedTasks.size() == 0)
            return;
        String getExistsTasks = "select taskid from t_task_info";
        StringBuffer cleanSql = new StringBuffer("delete from t_task_info  where taskid not in (");

        Set<String> scanedTaskIds = scanedTasks.keySet();
        Set<String> existTasks = Sets.newHashSet();
        for (String taskId : scanedTaskIds) {
            cleanSql.append("'").append(taskId).append("',");
        }
        cleanSql.deleteCharAt(cleanSql.length() - 1).append(")");

        this._delete(cleanSql.toString());
        List<Map<String, Object>> li = this._queryMultex(getExistsTasks);
        for (Map<String, Object> task : li) {
            existTasks.add((String) task.get("TASKID"));

        }

        SetView<String> newTaskIds = Sets.difference(scanedTaskIds, existTasks);
        String sql = "insert into t_task_info (id,TASKID,GROUPID,CRON,JOBNAME,BEAN,LASTSTATUS) values(SEQ_TASK_INFO.Nextval,?,?,?,?,?,?)";
        for (String taskid : newTaskIds) {
            this._insert(sql, scanedTasks.get(taskid).toArray());
        }
    }

    @Override
    public void initTask() {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        // 可执行的任务列表
        String sql = "select to_char(id) id,TASKID,GROUPID,CRON,JOBNAME,BEAN,LASTSTATUS from t_task_info order by groupid,taskid";
        List<Map<String, Object>> taskList = this._queryMultex(sql);
        for (Map<String, Object> task : taskList) {
            // 任务名称和任务组设置规则：
            // 名称：task_1 ..
            // 组 ：group_1 ..
            if ("n".equalsIgnoreCase((String) task.get("LASTSTATUS")))
                continue;
            try {
                TriggerKey triggerKey = TriggerKey.triggerKey((String) task.get("TASKID"),
                        (String) task.get("GROUPID"));
                CronTrigger trigger;

                trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

                // 不存在，创建一个
                if (null == trigger) {
                    JobDetail jobDetail = JobBuilder.newJob(QuartzTaskFactory.class)
                            .withIdentity((String) task.get("TASKID"), (String) task.get("GROUPID")).build();
                    jobDetail.getJobDataMap().put("scheduleJob", task);
                    // 表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule((String) task.get("CRON"));
                    // 按新的表达式构建一个新的trigger
                    trigger = TriggerBuilder.newTrigger()
                            .withIdentity((String) task.get("TASKID"), (String) task.get("GROUPID"))
                            .withSchedule(scheduleBuilder).build();

                    scheduler.scheduleJob(jobDetail, trigger);

                } else {
                    // trigger已存在，则更新相应的定时设置
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule((String) task.get("CRON"));
                    // 按新的cronExpression表达式重新构建trigger
                    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder)
                            .build();
                    // 按新的trigger重新设置job执行

                    scheduler.rescheduleJob(triggerKey, trigger);

                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

    }

}
